iT邦幫忙

2024 iThome 鐵人賽

DAY 12
0
生成式 AI

Local LLM infra & Inference 一部曲系列 第 12

Day12 - 壓榨你的GPU,讓使用率up up up:Batching

  • 分享至 

  • xImage
  •  

前言 - 什麼是Batching?

先前在 Day4 提到的吞吐量 (Throughput) 🚀 是伺服器在一定時間內可以處理的請求數量。透過增加吞吐量,可以同時為用戶提供更多服務,從而提高整體系統效能。

而Batching就是同時處理多個user request來提高吞吐量的基本方法。它的基本概念是將多個input request組成一個batch,然後同時處理這個batch中的所有項目,而不是一個一個地逐一處理。它同時也是最簡單提高GPU使用率的方式 🖥️,直接一口氣設定大的batch,一次收集多一點的輸入進行處理,可以減少參數載入的頻率。

🔍 簡單來說它的優點如下:

  1. 可以提高GPU計算效率 ⚡
  2. 減少I/O花費 💾
  3. 增加吞吐量 📊

如果沒有設定Batch,就是一次只能處理一個請求,導致資源的浪費。

https://ithelp.ithome.com.tw/upload/images/20240906/2016811540M6nvAFhZ.png
(圖源: 自製)

不過設定batch也要考慮自己VRAM可負荷的範圍喔! 🧠💡


📦 Static Batching (靜態批次)

最傳統的方法是設定一個固定值,這就是Static Batching。

但是LLM每次request的長度不一樣,也不知道每個request會產生多少tokens,在一個batch當中,有可能出現較短的request已經完成,而較長的request仍在推理當中。長的request一直卡著GPU不放,需要等待他全部完成後才會回傳結果。當遇到長度差異越大的request,這個現象會更明顯,這會導致GPU的使用率降低。

如下圖,第三個request在兩回合跌代就結束了,但它還是要等第二個request慢慢生成。

https://ithelp.ithome.com.tw/upload/images/20240905/20168115w1SkleQTG0.png
(圖源:anyscale,黃色:pre-fill(input tokens),藍色和紅色:decoding(生成的tokens))

🔄 Continuous Batching (連續批次)

為了解決靜態批次的問題,Orca: A Distributed Serving System for Transformer-Based Generative Models提出了Continuous Batching的方法。它不會在開始下一個batch之前等待所有batch完成,而是在batch當中的其中一個request已經被完成之後,就可以再它的位置調度新的request過去,增加了整體GPU的使用率。

如下圖,雖然乍看第一、三、四個request好像會遇到記憶體會不足的問題,但實際上因為到T8時,前面第一批request已經都到達了END,資源被釋放出來了,而總預留的記憶體通常是這個模型KV快取所需的最大數量tokens (max_tokens),所以並不會遇到生成不了的問題,這也是Continuous Batching的設計厲害的地方。

https://ithelp.ithome.com.tw/upload/images/20240905/20168115ZP8kNy2QdU.png
(圖源:anyscale)

不過這看似簡單的原理,實際應用上還是有一個缺點,就是它記憶體預留策略的問題,正是因為Continuous Batching會為KV快取保留max_tokens的記憶體,這代表除非requests都產生大量tokens,否則大部分預留的記憶體將不會被使用到


💸 那有多浪費呢? 💸

vLLM blog 提到他們發現有系統因為記憶體碎片 (fragmentation)和過度預留而浪費了60% - 80%的記憶體

https://ithelp.ithome.com.tw/upload/images/20240912/201681153fVC4FMNtD.jpg
(圖源: 論文 (Kwon et al., 2023))

如上圖,request A的最大序列長度為2048,request B的最大序列長度為512。這會出現三種類型的記憶體浪費:

  1. 保留 (Reserved) 🛑
  2. 內部碎片 (Internal Fragmentation) 🧩
  3. 外部碎片 (External Fragmentation) 🚧

其中,Reserved是為了確保request生成的穩定性,預留整個記憶體區塊,即使還沒使用的部分也不能被其他request利用;Internal Fragmentation是因系統不知道模型會產生多少個tokens而過度預留max_tokens而未使用的記憶體;External Fragmentation 是指當固定大小的記憶體區塊與不同長度的序列不匹配時,由記憶體分配器(memory allocator)造成的、無法利用的分散記憶體空間。

🔍 GPT4o的簡單比較:

外部碎片:想像你有一個抽屜,裡面有很多固定大小的小隔間。如果你放進不同大小的物品,某些隔間可能只能部分放滿,剩下的空間無法放入其他物品,這就是外部碎片。

內部碎片:同樣的抽屜裡,你分配了一個較大的隔間來放某個物品,但這個物品只占用了一部分空間,剩下的空間雖然已被劃分給這個物品,卻沒有被充分利用,這就是內部碎片。

而這個問題的解法會在下一章的記憶體管理PagedAttention被介紹到。📚✨


章節總結

這章節介紹了不同的Batching方式,也介紹了在LLM推理應用中常常看到的Continuous Batching,它夠加快request的處理速度,因為它允許batch當中的部分request提前處理完成,但由於它會預留大量記憶體,可能會有空間浪費,因此後續的實作可以在vLLM框架中體驗搭配PagedAttention輔助的效果,讓記憶體的分配更靈活。


參考資料

How continuous batching enables 23x throughput in LLM inference while reducing p50 latency
https://www.anyscale.com/blog/continuous-batching-llm-inference
LLM Inference: Continuous Batching and PagedAttention
https://insujang.github.io/2024-01-07/llm-inference-continuous-batching-and-pagedattention/


上一篇
Day11 - 沒有什麼是一個GPU不能解決的......Model Parallelization
下一篇
Day13 - 壓榨完GPU換壓榨VRAM:PagedAttention
系列文
Local LLM infra & Inference 一部曲30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言